//////////////////////////////////////////////////////////////////////
// 文件名称：MyStirng.h
// 功能描述：模拟实现std::string
// 创建标识：Aiye 2025/07/11 23:56:28
// 文件版权：1.0 接入STL迭代器、包含常见增删查改
//////////////////////////////////////////////////////////////////////
#pragma once
#include <iostream>
#include <iterator>

class string;
class MyString
{
public:
	/**
	 * @brief 普通构造函数
	 */
	MyString();

	/**
	 * @brief 拷贝构造函数
	 * @param [in] strValue	字符指针、C风格的字符串
	 */
	MyString(const char* pStrValue);

	/**
	 * @brief 拷贝构造函数
	 * @param [in] strValue	字符指针
	 * @param [in] nLen	指定长度
	 */
	MyString(const char* pStrValue , int nLen);

	/**
	 * @brief 拷贝构造函数 深拷贝
	 * @param [in] strValue 外部兼容std::string	
	 */
	MyString(const std::string strValue);

	/**
	 * @brief 拷贝构造函数 深拷贝
	 * @param [in] strValue	内部兼容 MyString
	 */
	MyString(const MyString& strValue);

	/**
	 * @brief 移动拷贝构造函数
	 * @param [out] strValue 内部兼容MyStirng
	 * noexpect 用于编译器优化
	 */
	MyString(MyString&& strValue) noexcept;

	/**
	 * @brief 赋值构造函数
	 * @param [in] strValue	
	 * @return 自身引用，支持链式调用
	 */
	MyString& operator = (const MyString& strValue);

	/**
	 * @brief 移动赋值构造函数
	 * @param [in] strValue	
	 * @return 
	 */
	MyString& operator = (MyString&& strValue) noexcept;

	/**
	 * @brief 析构函数
	 */
	~MyString();

public:
	/**
	 * @brief 用于交换两个对象的值
	 * @param [out] strValue	被交换的对象
	 */
	void swap(MyString& strValue);
	
	/**
	 * @brief 获取对象的容量
	 * @return 容量
	 */
	inline size_t capacity() const;

	/**
	 * @brief 获取对象的大小
	 * @return 大小
	 */
	inline size_t size() const;

	/**
	 * @brief 获取char*
	 * @return char*
	 */
	inline const char* c_str() const;

	/**
	 * @brief 清空对象
	 */
	void clear();

	/**
	 * @brief 分配大小，不改变size
	 * @param [in] nCapacity 容量大小	
	 */
	void reserve(size_t nCapacity);

	/**
	 * @brief 重新分配大小，改变size
	 * @param [in] nSize	
	 */
	void resize(size_t nSize ,char strData = '\0');

	/**
	 * @brief 压缩资源
	 */
	void shrink_to_fit();

	/**
	 * @brief 末尾追加
	 * @param [in] strValue	
	 */
	void append(const MyString& strValue);

	/**
	 * @brief 获取字符子串
	 * @param [in] nPos	获取的位置
	 * @param [in] nLen	获取的长度
	 * @return 字符子串
	 */
	MyString substr(size_t nPos, int nLen = SIZE_MAX);

	/**
	 * @brief 查找字符串首次出现子串的位置
	 * @param [in] strValue	需要查找的字符串
	 * @param [in] nPos	开始查找的位置
	 * @return 若找到返回索引，否则返回 -1
	 */
	size_t find(const MyString& strValue , size_t nPos = 0) const;

	/**
	 * @brief 比较两个字符串
	 * @param [in] strValue	
	 * @return 大于 、 等于 、小于
	 */
	int compare(const MyString& strValue) const;

	/**
	 * @brief 在指定位置插入字符串
	 * @param [in] nPos	指定位置 
	 * @param [in] strValue	插入的字符串
	 */
	void insert(size_t nPos, const MyString& strValue);

	/**
	 * @brief 消除字符串
	 * @param [in] nPos	位置
	 * @param [in] nLen	长度
	 */
	void erase(size_t nPos, size_t nLen);

	/**
	 * @brief 
	 * @param [in] nPos	
	 * @param [in] nLen	
	 * @param [in] strValue	
	 */
	void replace(size_t nPos, size_t nLen, const MyString& strValue);

public:
	
	MyString& operator + (const MyString& strValue);

	MyString& operator += (const MyString& strValue);

	char& operator [] (size_t nIndex);

	const char& operator [] (size_t nIndex) const;

	friend std::ostream& operator << (std::ostream& os, const MyString& strValue);

	friend std::istream& operator >> (std::istream& is, MyString& strValue);

public:
	/** @brief iterator 迭代器接口 */
	class iterator
	{
	public:
		using iterator_category = std::random_access_iterator_tag;//随机访问迭代器
		using value_type = char;//元素类型为char
		using difference_type = std::ptrdiff_t;//迭代器差值
		using pointer = char*;
		using reference = char&;

	public:
		/**
		 * @brief 构造迭代器指针
		 * @param [in] pStr	
		 */
		iterator(pointer pStr = nullptr);

	public:
		reference operator * () const;
		pointer operator -> () const;
		iterator& operator ++ ();
		iterator& operator ++ (int);
		iterator& operator -- ();
		iterator& operator -- (int);
		iterator& operator - (difference_type type) const;
		iterator& operator + (difference_type type) const;
		difference_type operator - (const iterator& itValue) const;

		bool operator == (const iterator& itValue) const;
		bool operator != (const iterator& itValue) const;
		bool operator <= (const iterator& itValue) const;		
		bool operator >= (const iterator& itValue) const;
		bool operator < (const iterator& itValue) const;
		bool operator > (const iterator& itValue) const;

	private:
		pointer _pStr;
	};

	/** @brief const_iterator 常量迭代器接口; */
	class const_iterator
	{
	public:
		using iterator_category = std::random_access_iterator_tag;
		using value_type = const char;
		using difference_type = std::ptrdiff_t;
		using pointer = const char*;
		using reference = const char&;

	public:
		const_iterator(pointer ptr = nullptr);

	public:
		reference operator*() const;
		pointer operator->() const;
		const_iterator& operator ++ ();
		const_iterator operator ++ (int);
		const_iterator& operator -- ();
		const_iterator operator -- (int); 
		const_iterator operator + (difference_type type) const;
		const_iterator operator - (difference_type type) const;
		difference_type operator - (const const_iterator& itValue);

		bool operator == (const const_iterator& itValue) const;
		bool operator != (const const_iterator& itValue) const;		
		bool operator > (const const_iterator& itValue) const;
		bool operator < (const const_iterator& itValue) const;
		bool operator <= (const const_iterator& itValue) const;
		bool operator >= (const const_iterator& itValue) const;

	private:
		pointer _ptr;
	};

public:
	/**
	 * @brief 获取可读写迭代器起始位置。
	 */
	iterator begin();

	/**
	 * @brief 获取可读写迭代器末尾位置。
	 */
	iterator end();

	/**
	 * @brief 获取常量迭代器起始位置。
	 */
	const_iterator cbegin() const;

	/**
	 * @brief 获取常量迭代器末尾位置。
	 */
	const_iterator cend() const;

private:
	/**
	 * @brief 内存扩展,当容大小与实际大小相等需要扩展
	 * @param [in] _mincapacity	
	 */
	void ensure_capacity(size_t _minCapacity);

private:
	char* _pStrData;		//数据
	size_t _nSize;			//尺寸，实际存放字符的数量
	size_t _nCapacity;		//容量，不包括结束标识符
};

